package com.doctcloud.datacloud.service;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.doctcloud.common.core.utils.bean.BeanUtils;
import com.doctcloud.datacloud.entity.OrdersEntity;
import com.doctcloud.datacloud.mapper.OrdersEntityMapper;
import com.doctcloud.hisinfo.api.RemoteHisOrdadmService;
import com.doctcloud.hisinfo.histable.domain.ordadm.OrdersDo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrdersEntityService extends ServiceImpl<OrdersEntityMapper, OrdersEntity> {

    @Value("${sync.batch.size:500}")
    private int BATCH_SIZE;

    private final RemoteHisOrdadmService remoteHisOrdadmService;

    /**
     * 同步指定患者、指定住院记录的医嘱信息。
     * 增加了 @Transactional 注解，确保数据操作的原子性。
     *
     * @param patientId 患者ID
     * @param visitId   住院标识
     */
    @Transactional
    public void syncPat(String patientId, Integer visitId) {
        log.info("--- 开始同步患者ID [{}], 住院标识 [{}] 的医嘱数据 ---", patientId, visitId);
        long startTime = System.currentTimeMillis();

        try {
            // 1. 从远程服务获取数据
            List<OrdersDo> remoteOrders = remoteHisOrdadmService.listOrdersByPat(patientId, visitId);
            if (CollectionUtils.isEmpty(remoteOrders)) {
                log.warn("从远程服务获取患者ID [{}], 住院标识 [{}] 的医嘱信息为空，同步任务终止。", patientId, visitId);
                return;
            }
            log.info("从远程服务获取到 {} 条医嘱信息。", remoteOrders.size());

            // 2. 数据转换与过滤
            List<OrdersEntity> entitiesToUpsert = remoteOrders.stream()
                    .filter(this::isValidOrder)       // 将过滤逻辑提取到独立方法
                    .map(this::convertToEntity)       // 将转换逻辑提取到独立方法
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(entitiesToUpsert)) {
                log.info("患者ID [{}], 住院标识 [{}] 没有需要同步的有效医嘱记录。", patientId, visitId);
                return;
            }
            log.info("准备执行批量UPSERT操作，共 {} 条记录，分批大小：{}。", entitiesToUpsert.size(), BATCH_SIZE);

            // 3. 执行分批批量UPSERT操作
            int totalAffectedRows = 0;
            int totalBatches = (int) Math.ceil((double) entitiesToUpsert.size() / BATCH_SIZE);

            for (int i = 0; i < totalBatches; i++) {
                int startIndex = i * BATCH_SIZE;
                int endIndex = Math.min(startIndex + BATCH_SIZE, entitiesToUpsert.size());
                List<OrdersEntity> batchEntities = entitiesToUpsert.subList(startIndex, endIndex);

                log.debug("正在执行第 {} 批/共 {} 批，处理 {} 条记录。", i + 1, totalBatches, batchEntities.size());
                int affectedRows = baseMapper.batchUpsert(batchEntities);
                totalAffectedRows += affectedRows;
            }

            log.info("--- 同步完成。患者ID [{}], 住院标识 [{}]。总耗时：{} ms。数据库受影响的总行数: {} ---",
                    patientId, visitId, System.currentTimeMillis() - startTime, totalAffectedRows);

        } catch (Exception e) {
            log.error("同步患者ID [{}], 住院标识 [{}] 的医嘱信息时发生异常: ", patientId, visitId, e);
            // 异常会自动触发事务回滚，并向上抛出
            throw e;
        }
    }

    /**
     * 校验 OrdersDo 对象是否有效。
     */
    private boolean isValidOrder(OrdersDo doObj) {
        return doObj != null &&
                doObj.getPatientId() != null && !doObj.getPatientId().trim().isEmpty() &&
                doObj.getVisitId() != null &&
                doObj.getOrderClass() != null && !doObj.getOrderClass().trim().isEmpty() &&
                doObj.getOrderCode() != null && !doObj.getOrderCode().trim().isEmpty() &&
                doObj.getOrderNo() != null &&
                doObj.getOrderSubNo() != null;
    }

    /**
     * 将 OrdersDo 转换为 OrdersEntity。
     * 使用 BeanUtils 简化代码，前提是字段名和类型完全匹配。
     */
    private OrdersEntity convertToEntity(OrdersDo doObj) {
        OrdersEntity entity = new OrdersEntity();
        BeanUtils.copyProperties(doObj, entity);
        return entity;
    }
}